package com.mezz.bones.framework.websocket.boot;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.mezz.bones.framework.websocket.handler.WebSocketHeartbeatHandler;
import com.mezz.bones.framework.websocket.handler.WebSocketMessageHandler;
import com.mezz.bones.framework.websocket.service.WebSocketSessionManager;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * JSR-356 标准的 WebSocket 服务端
 *
 * @author Lion Li
 */
@Slf4j
@Component
@ServerEndpoint(value = "/ws/{userId}")
public class WebSocketServer {

    /**
     * 具体的连接设备
     */
    private Session session;

    /**
     * 连接的用户标识ID
     */
    private String userId;

    private WebSocketSessionManager webSocketSessionManager;
    private WebSocketMessageHandler webSocketMessageHandler; // 业务处理器

    private WebSocketHeartbeatHandler webSocketHeartbeatHandler;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        this.userId = userId;

        try {
            this.webSocketSessionManager = SpringUtil.getBean(WebSocketSessionManager.class);
            this.webSocketMessageHandler = SpringUtil.getBean(WebSocketMessageHandler.class);
            this.webSocketHeartbeatHandler = SpringUtil.getBean(WebSocketHeartbeatHandler.class);
        } catch (Exception e) {
            log.error("[WebSocket Init] 获取Spring Bean失败: {}", e.getMessage());
            try {
                session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "Server configuration error"));
            } catch (IOException ex) {
                log.error("[WebSocket Close] 关闭会话失败: {}", ex.getMessage());
            }
            return;
        }

        if (StrUtil.isBlank(userId)) {
            log.warn("[WebSocket Connect] ConnectId为空，关闭会话: {}", session.getId());
            try {
                session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "connectId can not be blank"));
            } catch (IOException e) {
                log.error("[WebSocket Close] 关闭会话失败: {}", e.getMessage());
            }
            return;
        }


        //会话绑定
        webSocketSessionManager.addSession(userId, session);
        int connectionCount = webSocketSessionManager.getSessionCount(userId);
        log.info("[WebSocket Connect] 新连接建立 - connectId={}, sessionId={}, uri={}, 当前连接数={}",
                userId, session.getId(), session.getRequestURI(), connectionCount);
        
        // 启动心跳任务
        if (webSocketHeartbeatHandler != null) {
            webSocketHeartbeatHandler.startHeartbeatTask(session,webSocketMessageHandler.heartBeatData());
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        if (webSocketHeartbeatHandler != null) {
            webSocketHeartbeatHandler.stopHeartbeatTask(session);
        }
        if (this.webSocketSessionManager != null && StrUtil.isNotBlank(this.userId)) {
            this.webSocketSessionManager.removeSession(this.userId, session);
            int remainingConnections = webSocketSessionManager.getSessionCount(userId);
            log.info("[WebSocket Close] 连接关闭 - connectId={}, sessionId={}, 剩余连接数={}",
                    this.userId, session.getId(),
                    remainingConnections);
        } else {
            log.warn("[WebSocket Close] 连接关闭但未正确清理 - sessionId={}", session.getId());
        }
        
        // 停止心跳任务
        if (webSocketHeartbeatHandler != null) {
            webSocketHeartbeatHandler.stopHeartbeatTask(session);
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("Received message from connectId={}, sessionId={}: {}", this.userId, session.getId(), message);
        try {
            // 假设 webSocketMessageHandler.handle 需要 connectId, message 和 session
            // 并且它会处理响应的发送
            this.webSocketMessageHandler.handleMessage(this.userId, message, session);
        } catch (Exception e) {
            log.error("Error processing message for connectId={}, sessionId={}: {}", this.userId, session.getId(), e.getMessage(), e);
            // 可以考虑向客户端发送错误信息
            try {
                session.getBasicRemote().sendText("Error processing your request: " + e.getMessage());
            } catch (IOException ex) {
                log.error("Error sending error message to client {}: {}", session.getId(), ex.getMessage());
            }
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("[WebSocket异常] 连接发生错误 - connectId={}, sessionId={}, 错误信息={}", 
                this.userId, session.getId(), error.getMessage(), error);
        
        // 发生错误时，也尝试从管理器中移除会话，并关闭会话
        if (this.webSocketSessionManager != null && StrUtil.isNotBlank(this.userId)) {
            this.webSocketSessionManager.removeSession(this.userId, session);
            int remainingConnections = webSocketSessionManager.getSessionCount(userId);
            log.info("[WebSocket Close] 因异常关闭连接 - connectId={}, sessionId={}, 剩余连接数={}",
                    this.userId, session.getId(), remainingConnections);
        }

        // 停止心跳任务
        if (webSocketHeartbeatHandler != null) {
            webSocketHeartbeatHandler.stopHeartbeatTask(session);
        }
        
        // 尝试关闭会话，如果它仍然打开
        if (session.isOpen()) {
            try {
                session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "Internal server error"));
            } catch (IOException e) {
                log.error("[WebSocket Close] 关闭异常会话失败 - sessionId={}, 错误信息={}",
                        session.getId(), e.getMessage());
            }
        }
    }
}
